<template>
  <div v-loading="g_loading">
    <div id="forceD3" ref="forceD3" style="height:calc(100vh - 190px);" />

    <!-- 添加或修改产权信息对话框 -->
    <el-dialog :title="$t(propertyName)" :visible.sync="propertyFundFormOpen" :close-on-click-modal="false" :lock-scroll="false" custom-class="dialogForm" append-to-body>
      <propertyFundForm ref="propertyFundForm" />
    </el-dialog>

    <el-dialog :title="$t(propertyName)" :visible.sync="propertyCompanyFormOpen" :close-on-click-modal="false" :lock-scroll="false" custom-class="dialogForm" append-to-body>
      <PropertyCompanyForm ref="propertyCompanyForm" />
    </el-dialog>
  </div>
</template>

<script>
import * as d3 from 'd3'
var i = 0
import { getGraph } from '@/api/fund/property/propertyFund.js'
import propertyFundForm from './propertyFundForm.vue'
import PropertyCompanyForm from '@/views/company/propertyCompany/propertyCompanyForm'
const { moneyFormat } = require('@/utils/ruoyi')
export default {
  name: 'SeeksRelationGraphDemo',
  components: { PropertyCompanyForm, propertyFundForm },
  data() {
    return {
      g_loading: true,
      propertyFundFormOpen: false,
      propertyCompanyFormOpen: false,
      propertyName: '',
      duration: 400,
      root: null,
      lastClickD: null,
      container: null,
      barHeight: 50,
      clientWidth: 20
    }
  },
  created() {
  },
  mounted() {
    this.$nextTick(() => {
      this.load()
    })
  },
  methods: {
    load() {
      var svg = d3.select('#forceD3').append('svg')
        .attr('class', 'svg')
        .attr('width', '100%')
        .attr('height', '100%')
        .on('dblclick.zoom', null)

      this.container = svg.append('g')
        .attr('transform', 'translate(' + this.clientWidth + ',20)scale(0.9)')
        .attr('class', 'container')

      svg.call(d3.zoom()
        .scaleExtent([1 / 2, 4])
        .on('zoom', this.zoomFn))
        .on('dblclick.zoom', function() {
          d3.event.stopPropagation() // silence other listeners
          d3.event.preventDefault()
        })

      this.setGraphData()
    },
    setGraphData() {
      getGraph().then(res => {
        if (res.code === 200) {
          this.g_loading = false
          this.root = d3.hierarchy(res.data)
          this.root.x0 = 0
          this.root.y0 = 0
          this.update(this.root)
        }
      })
    },
    zoomFn() {
      const transform = d3.event.transform
      this.container.attr('transform', 'translate(' + (transform.x + this.clientWidth) + ',' + (transform.y) + ')scale(' + (transform.k) * 0.9 + ')')
    },
    update(source) {
      // Compute the flattened node list.
      var nodes = this.root.descendants()
      var height = Math.max(1000, nodes.length * this.barHeight + 40)

      d3.select('svg').transition()
        .duration(this.duration)
        .attr('height', height)

      d3.select(self.frameElement).transition()
        .duration(this.duration)
        .style('height', height + 'px')

      // Compute the "layout". TODO https://github.com/d3/d3-hierarchy/issues/67
      var index = -1
      var count = 0
      var _this = this
      _this.root.eachBefore(function(n) {
        count += 20
        n.style = 'node_' + n.depth
        n.x = ++index * _this.barHeight + count
        n.y = n.depth * 20
      })

      // Update the nodes…
      var node = this.container.selectAll('.node')
        .data(nodes, function(d) { return d.id || (d.id = ++i) })

      var nodeEnter = node.enter().append('g')
        .attr('class', function(d) { return 'node node_' + d.depth + ' ' + _this.getClass(d) })
        .attr('transform', function() { return 'translate(' + source.y0 + ',' + source.x0 + ')' })
        .style('opacity', 0)

      // Enter any new nodes at the parent's previous position.
      nodeEnter.append('rect')
        .attr('y', -_this.barHeight / 2)
        .attr('height', _this.barHeight)
        .attr('width', '700px')
        .style('stroke', '#E5E6E7')
        .style('fill', '#fff')
        .style('stroke-width', '0.5px')

      nodeEnter.append('rect')
        .attr('y', -_this.barHeight / 2)
        .attr('height', _this.barHeight)
        .attr('width', 3)
        // .style('fill', '#339DFF')
        .style('fill', function(d) {
          if (d) {
            if (d.data.type === 'fund') {
              return '#11b95c'
            } else {
              return '#339DFF'
            }
          }
        })

      nodeEnter.append('text')
        .attr('dy', function(d) {
          if (d) {
            if (!d.data.shareNumProportion) {
              return 5
            } else {
              return -3.5
            }
          }
        })
        .attr('dx', 40)
        .style('font-size', '14px')
        .text(function(d) {
          // console.log(d)
          // if (d.data.name.length > 9) {
          //   return d.data.name.substring(0, 10) + '...'
          // }
          return d.data.name
        })

      nodeEnter.append('text')
        .attr('dy', 15.5)
        .attr('dx', 40)
        .style('fill', '#797979')
        .style('font-size', '12px')
        .html(function(d) {
          if (d.data.shareNumProportion) {
            return '持股：<tspan style="fill:#FF8527;">' + d.data.shareNumProportion + ' %' + '</tspan>'
          }
        })

      nodeEnter.append('text')
        .attr('dy', 15.5)
        .attr('dx', 150)
        .style('fill', '#797979')
        .style('font-size', '12px')
        .html(function(d) {
          if (d.data.shareNumProportion) {
            return '金额：<tspan style="fill:#FF8527;">' + moneyFormat(d.data.money, 'w') + ' 万' + '</tspan>'
          }
        })
      nodeEnter.append('text')
        .attr('dy', 5.5)
        .attr('dx', 650)
        .style('font-size', '14px')
        .style('fill', '#359FFB')
        .style('cursor', 'pointer')
        .text(function() {
          return '详情'
        })
        .on('click', function(d) {
          console.log('详情', d)
          _this.propertyView(d.data)
        })

      var circle = nodeEnter.append('g')
        .attr('class', 'circle')
        .on('click', this.click)

      circle.append('circle')
        .style('fill', '#fff')
        .style('stroke', '#D9D8D8')
        .style('stroke-width', 1)
        .style('cursor', 'pointer')
        .attr('r', function(d) {
          if (d.children) {
            return 8.5
          } else if (d._children) {
            return 8.5
          } else {
            return
          }
        })

        .attr('transform', function() {
          return 'translate(20,0)'
        })

      circle.append('text')
        .attr('dy', 4.5)
        .attr('cx', '20px')
        .attr('cy', '30px')
        .attr('font-family', 'FontAwesome')
        .attr('text-anchor', 'middle')
        .attr('class', 'fa')
        .style('font-size', '15px')
        .style('cursor', 'pointer')
        .style('fill', function() {
          return '#D9D8D8'
        })
        .attr('transform', function() {
          return 'translate(20,0)'
        })
        .text(function(d) {
          if (d.children) {
            return '-'
          } else if (d._children) {
            return '+'
          } else {
            return ''
          }
        })
      node.select('.fa')
        .text(function(d) {
          if (d.children) {
            return '-'
          } else if (d._children) {
            return '+'
          } else {
            return ''
          }
        })

      // Transition nodes to their new position.
      nodeEnter.transition()
        .duration(this.duration)
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')' })
        .style('opacity', 1)

      node.transition()
        .duration(this.duration)
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')' })
        .style('opacity', 1)
        .select('rect')
        .style('stroke', '#E5E6E7')
        .style('fill', this.color)

      // Transition exiting nodes to the parent's new position.
      node.exit().transition()
        .duration(this.duration)
        .attr('transform', function() { return 'translate(' + source.y + ',' + source.x + ')' })
        .style('opacity', 0)
        .remove()

      // Update the links…
      var link = this.container.selectAll('.link')
        .data(this.root.links(), function(d) { return d.target.id })

      // Enter any new links at the parent's previous position.
      link.enter().insert('path', 'g')
        .attr('class', function(d) {
          return 'link link_' + d.target.depth + ' ' + _this.getClass(d.target)
        })
        .attr('fill', function() {
          return 'none'
        })
        .attr('stroke', function() {
          return '#e0e0e0'
        })
        .attr('stroke-width', function() {
          return '0.5px'
        })
        .attr('d', function() {
          var o = { x: source.x0, y: source.y0 }
          return _this.elbow({ source: o, target: o })
        })
        .transition()
        .duration(_this.duration)
        .attr('d', _this.elbow)

      // Transition links to their new position.
      link.transition()
        .duration(_this.duration)
        .attr('d', _this.elbow)

      // Transition exiting nodes to the parent's new position.
      link.exit().transition()
        .duration(_this.duration)
        .attr('d', function() {
          var o = { x: source.x, y: source.y }
          return _this.elbow({ source: o, target: o })
        })
        .remove()

      // Stash the old positions for transition.
      this.root.each(function(d) {
        d.x0 = d.x
        d.y0 = d.y
      })
    },
    click(d) {
      if (d.children) {
        d._children = d.children
        d.children = null
      } else {
        d.children = d._children
        d._children = null
      }
      if (this.lastClickD) {
        this.lastClickD._isSelected = false
      }
      d._isSelected = true
      this.lastClickD = d
      this.update(d)
    },

    getClass(d) {
      if (d.data.class) {
        return d.data.class
      } else {
        return ''
      }
    },
    elbow(d) {
      return 'M' + d.source.y + ',' + d.source.x +
        'H' + (d.source.y + (d.target.y - d.source.y) / 2) +
        'V' + d.target.x +
        'H' + d.target.y
    },
    color(d) {
      if (d._isSelected) return '#fff'
      return d._children ? '#fff' : d.children ? '#fff' : '#fff'
    },
    /** 修改按钮操作 */
    propertyView(row) {
      if (row.type === 'company') {
        this.propertyCompanyFormOpen = true
        this.propertyName = row.name
        this.$nextTick(() => {
          this.$refs.propertyCompanyForm.init(row, 'BG')
        })
      } else {
        this.propertyFundFormOpen = true
        this.propertyName = row.name
        this.$nextTick(() => {
          this.$refs.propertyFundForm.init(row)
        })
      }
    }
  }
}
</script>
<style lang="scss" scoped>
/deep/.rel-node{
  text-align: left!important;
  padding: 8px;
  height: 46px;
  display: flex;
}
/deep/.graph_main{
  position: relative;
  display: flex;
  align-items: center;
  span{
    flex: 1;
    min-width: calc(100% - 20px);
    font-size: 11px;
    word-break: break-all;
    line-height: 15px;
    overflow: hidden;
    text-overflow: ellipsis;  /* 超出部分省略号 */
    word-break: break-all;  /* break-all(允许在单词内换行。) */
    display: -webkit-box; /* 对象作为伸缩盒子模型显示 */
    -webkit-box-orient: vertical; /* 设置或检索伸缩盒对象的子元素的排列方式 */
    -webkit-line-clamp: 2; /* 显示的行数 */
  }
  i{
    font-style: normal;
    white-space: nowrap;
    cursor: pointer;
    width: 15px;
    height: 15px;
    border: 1px solid;
    border-radius: 50%;
    font-size: 11px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 400;
  }
}
</style>
